package com.inspur.cloud.controller.resource;

import com.inspur.cloud.entity.dataspace.ao.resource.HdfsAO;
import com.inspur.cloud.entity.dataspace.common.OpEntityResult;
import com.inspur.cloud.entity.dataspace.common.PageReqParam;
import com.inspur.cloud.entity.dataspace.common.PageResult;
import com.inspur.cloud.entity.dataspace.vo.HdfsReq;
import com.inspur.cloud.entity.dataspace.vo.HdfsVO;
import com.inspur.cloud.enums.QuotaEnum;
import com.inspur.cloud.security.AuthorizationHelper;
import com.inspur.cloud.service.dataspace.HdfsManagerService;
import com.inspur.cloud.util.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.security.RolesAllowed;

@RestController
@RequestMapping("/dataspace/api/v1/hdfs")
@Api(value = "hdfs", description = "hdfs资源管理")
public class HdfsManagerController {
    @Autowired
    HdfsManagerService hdfsManagerService;

    @RequestMapping(value = "/list",method = { RequestMethod.POST })
    @ApiOperation(value = "资源列表", notes = "")
    public PageResult<HdfsAO> list(@ApiParam(value = "hdfs查询对象,json格式请求")
                         @RequestBody PageReqParam<HdfsReq> hdfsReq) {
        Integer pageIndex = hdfsReq.getPageIndex();
        Integer pageSize = hdfsReq.getPageSize();
        PageResult<HdfsAO> result = new PageResult<>();
        if (pageIndex == null || pageIndex < 0 || pageSize == null || pageSize < 1 || pageSize > 50) {
            result.setCode(-1);
            result.setMsg("分页参数不正确");
            return result;
        }
        if (hdfsReq.getReqParam() == null) {
            result.setCode(-1);
            result.setMsg("查询参数不完整");
            return result;
        }
        result = hdfsManagerService.list(hdfsReq);
        result.setMsg("查询成功");
        result.setCode(1);
        return result;
    }

    @PostMapping("/addRes")
    @ApiOperation(value = "新建hdfs资源，返回数据库里的资源id", notes = "路径需要传完整的绝对路径")
    @RolesAllowed({"Admin", "Tenant"})
    public OpEntityResult<Integer> addRes(@ApiParam(value = "hdfs传参")
                                          @RequestBody HdfsVO hdfsVO) throws Exception {
        OpEntityResult<Integer> result = new OpEntityResult(1,"新建成功");
        String path=hdfsVO.getUrl().toLowerCase();//这里还需要拼接路径
        hdfsVO.setUrl(path);
        if (hdfsVO.getParentId() == null) hdfsVO.setParentId(0);
        if(StringUtil.isEmpty(path)){
            return OpEntityResult.fail("目录名必传");
        }
        if (hdfsVO.getUnit() == null) {
            return OpEntityResult.fail("配额单位（M/G/T）必传");
        }
        if (hdfsVO.getCapacity() == null || hdfsVO.getCapacity() == 0) {
            return OpEntityResult.fail("配额大小不能为空或0");
        }
        if(hdfsVO.getParentId()==null && StringUtil.getLevel(path)>1){
            return OpEntityResult.fail("父级目录ID必传");
        }
        if (hdfsVO.getFileNum() == null || hdfsVO.getFileNum() < 1) {
            return OpEntityResult.fail("文件数不能为0");
        }
        if (AuthorizationHelper.isTenant() && (hdfsVO.getParentId() == 0 || StringUtil.getLevel(hdfsVO.getUrl()) <= 1)) {
            return OpEntityResult.fail("租户不允许在此目录下创建子文件（夹）");
        }
        if (hdfsManagerService.existPath(path)) {
            //下面可能会因为数据库比较慢导致异常，先这么判断，后期需要加锁优化
            return OpEntityResult.fail("要创建的资源路径已存在");
        }
        Long unUsed = hdfsManagerService.remain(hdfsVO.getParentId());
        Long quota = hdfsVO.getCapacity() * QuotaEnum.getSizeByType(hdfsVO.getUnit());
        if (unUsed < quota) {
            return OpEntityResult.fail("剩余空间不足分配");
        }
        OpEntityResult<Integer> remainFileNum = hdfsManagerService.remainFileNum(hdfsVO.getParentId());
        Integer unUsedFileNum = remainFileNum.getData();
        Integer quotaFileNum = hdfsVO.getFileNum();
        if (unUsedFileNum < quotaFileNum) {
            return OpEntityResult.fail("剩余文件数不足分配");
        }
        result=hdfsManagerService.addRes(hdfsVO);
        return result;
    }

    @PostMapping("/modifyRes")
    @ApiOperation(value = "修改hdfs资源，需要传资源ID", notes = "")
    @RolesAllowed({"Admin", "Tenant"})
    public OpEntityResult<Integer> modifyRes(@ApiParam(value = "hdfs传参")
                                             @RequestBody HdfsVO hdfsVO) {
        OpEntityResult<Integer> result = new OpEntityResult(1,"编辑成功");
        if(!AuthorizationHelper.isAdmin() && !AuthorizationHelper.isTenant()){
            result.setCode(-1);
            result.setMsg("非租户及管理员没有编辑资源的权限");
            return result;
        }
        if(hdfsVO.getResourceId()==null){
            result.setCode(-1);
            result.setMsg("资源ID必传");
            return result;
        }
        if (hdfsVO.getUnit() == null) {
            return OpEntityResult.fail("配额单位（M/G/T）必传");
        }
        if (hdfsVO.getCapacity() == null || hdfsVO.getCapacity() == 0) {
            return OpEntityResult.fail("配额大小不能为空或0");
        }
        if (hdfsVO.getFileNum() == null || hdfsVO.getFileNum() < 1) {
            return OpEntityResult.fail("文件数不能为0");
        }
        result=hdfsManagerService.modifyRes(hdfsVO);
        return result;
    }

    @PostMapping("/distributeRes")
    @ApiOperation(value = "分配hdfs资源，需要传资源ID", notes = "")
    public OpEntityResult<Integer> distributeRes(@ApiParam(value = "hdfs传参")
                                                 @RequestBody HdfsVO hdfsVO) {
        OpEntityResult<Integer> result;
        if(hdfsVO.getType() == null){
            return OpEntityResult.fail("type参数必传");
        }
        if(!AuthorizationHelper.isAdmin() && !AuthorizationHelper.isTenant()){
            return OpEntityResult.fail("非管理员/租户没有分配资源的权限");
        }
        if(hdfsVO.getResourceId()==null){
            return OpEntityResult.fail("资源ID必传");
        }
        result=hdfsManagerService.disRes(hdfsVO);
        return result;
    }

    @DeleteMapping("/delRes")
    @ApiOperation(value = "删除hdfs资源", notes = "暂不支持保存真实数据到回收站功能,仅做标记")
    @RolesAllowed({"Admin", "Tenant"})
    public OpEntityResult<Boolean> delRes(
                                          @ApiParam(value = "资源ID")
                                          @RequestParam(value = "resourceId",required = true) Integer resourceId,
                                          @ApiParam(value = "是否保留数据，1保留0不保留")
                                          @RequestParam(value = "keepData", required = true) Integer keepData) {
        OpEntityResult<Boolean> result = new OpEntityResult();
        if(!AuthorizationHelper.isAdmin() && !AuthorizationHelper.isTenant()){
            result.setCode(-1);
            result.setMsg("非租户及管理员没有删除资源的权限");
            result.setData(false);
            return result;
        }
        if(resourceId==null){
            result.setCode(-1);
            result.setMsg("资源ID不能为空");
            result.setData(false);
            return result;
        }
        result = hdfsManagerService.delRes(resourceId, keepData);
        return result;
    }

    @PostMapping("/shareRes")
    @ApiOperation(value = "分享hdfs资源，需要传资源ID", notes = "")
    public OpEntityResult<Integer> shareRes(@ApiParam(value = "hdfs传参")
                                            @RequestBody HdfsVO hdfsVO) {
        OpEntityResult<Integer> result = new OpEntityResult();
        if(!AuthorizationHelper.isAdmin() && !AuthorizationHelper.isTenant()){
            result.setCode(-1);
            result.setMsg("非管理员没有分配资源的权限");
            return result;
        }
        if (hdfsVO.getResourceId() == null) {
            return OpEntityResult.fail("资源ID为空必传");
        }
        return hdfsManagerService.share(hdfsVO);
    }

    @GetMapping("/remain")
    @ApiOperation(value = "获取上一级目录可用空间，需要传资源URL,返回-1表示没有限制", notes = "思路：找到其父目录，用父目录空间减去已经存在的兄弟节点空间，就是剩下可用的空间。")
    public OpEntityResult<Long[]> remain(@ApiParam(value = "父级ID")
                                         @RequestParam(value = "parentId") Integer parentId
    ) {
        if(parentId==null){
            return OpEntityResult.fail("父级ID不可为空");
        }
        OpEntityResult<Long[]> result = new OpEntityResult();
        result.setData(hdfsManagerService.getRemain(parentId));
        result.setCode(1);
        result.setMsg("查询成功");
        return result;
    }

    @GetMapping("/remainFileNum")
    @ApiOperation(value = "获取上一级目录可用文件数，需要传资源URL,返回-1表示没有限制", notes = "思路：找到其父目录，用父目录文件数减去已经存在的兄弟节点，就是剩下可用的数量。")
    public OpEntityResult<Integer> remainFileNum(@ApiParam(value = "父级ID")
                                                 @RequestParam(value = "parentId", required = true) Integer parentId
    ) {
        OpEntityResult<Integer> result = new OpEntityResult(1, "获取成功", -1);
        if (parentId == null) {
            return OpEntityResult.fail("父级ID不可为空");
        }
        return hdfsManagerService.remainFileNum(parentId);
    }
}
